package edu.kit.los.servlets;

import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.gson.Gson;

import edu.kit.los.Utils;
import edu.kit.los.event.FacebookEvent;
import edu.kit.los.event.StandardEvent;

/**
 * Servlet, das Anfragen an Facebook verwaltet.
 * @author Felix Kiechle, Benedikt Fuss  AIFB@BKIT
 */

public class FacebookLookup extends HttpServlet {
	/**
	 * für Serialisierung
	 */
	private static final long serialVersionUID = 3007920263418191773L;

	/**
	 * Führt ein asynchrones Lookup auf verschiedene FacebookEvents durch und schreibt sie 
	 * als RDF/XML auf den Output Stream. 
	 * 
	 * @param HttpservletRequest request      
	 * @param HttpServletResponse response
	 * @throws ServletException
	 * @throws IOExceptionn
	 * 	 
	*/
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType(Servlet.contentType_RDF);
		OutputStream out = response.getOutputStream();
		edu.kit.los.Model model = new edu.kit.los.Model();
		java.util.List<URL> url_list = getUrlList(request, response);
		URLFetchService fetcher = URLFetchServiceFactory.getURLFetchService();
		ArrayList<Future<HTTPResponse>> asyncResponses = new ArrayList<Future<HTTPResponse>>();
		//Asynchrone Anfrage für jede URL/jedes Event
		for (URL url : url_list) {
			Future<HTTPResponse> responseFuture = fetcher.fetchAsync(url);
			asyncResponses.add(responseFuture);
		}
		for (Future<HTTPResponse> future : asyncResponses) {
			HTTPResponse responseAsync;
			try {
				//Anfrage durchführen und Ergebnis zwischenspeichern
				responseAsync = future.get();
				byte[] array = responseAsync.getContent();
				String string = new String(array);
				//Gson-Objekt in Standardevent umwandeln und in Liste speichern
				Gson gson = new Gson();
				FacebookEvent event = gson.fromJson(string, FacebookEvent.class);
				model.addEvent(new StandardEvent(event));
			} 
			catch (InterruptedException e) {
				e.printStackTrace();
			} 
			catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		model.writeRDF(out);
	}

	/**
	 * Gibt die Liste der URLs zu den einzelnen Facebookevents einer Anfrage zurück
	 * @param request
	 * @param response
	 * @return Liste der URLs zu den Events, welche aus der Anfrage resultieren
	 * @throws ServletException
	 * @throws IOException
	 */
	public List<URL> getUrlList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, String> param = Servlet.parameters(request);
		String query = param.get("query");
		int limit = Integer.parseInt(param.get("limit"));
		java.util.List<URL> url_list = new LinkedList<URL>();
		// URL für Suchanfrage
		String url_encoded = "http://graph.facebook.com/search?q="
				+ query + "&type=event&limit=" + limit+"&fields=name";
		URL overview_url = null;
		try {
			overview_url = new URL(url_encoded);
		} 
		catch (MalformedURLException e) {
			e.printStackTrace();
		}

		String str = "";
		str = Utils.lookup_event_String(overview_url);

		int pos = 0;
		while (pos != -1) {
			pos = str.indexOf("\"id\":", pos);
			if (pos != -1) {
				//URL generieren
				url_list.add(new URL("http://graph.facebook.com/"
						+ str.substring(pos + 6, pos + 21)));
				pos++;
			}
		}
		return url_list;
	}
}
